#include "c_generator.h"
#include "pp_utils.h"
#include "pp_generator.h"

#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>

#define PP_GEN_C_VERSION "1.0.0"

#define JSON_TYPE_NONE      "none"
#define JSON_TYPE_NATIVE    "native"
namespace pp
{
    const std::map<std::string, std::string> TYPES_MAP = {
        {"uint8", "uint8_t"}, {"int8", "int8_t"},
        {"uint16", "uint16_t"}, {"int16", "int16_t"},
        {"uint32", "uint32_t"}, {"int32", "int32_t"},
        {"uint64", "uint64_t"}, {"int64", "int64_t"},
        {"float32", "float"}, {"float64", "double"},
        {"float", "float"}, {"double", "double"},
        {"string", "char"},
    };

    const std::map<std::string, std::string> TYPES_FUNC_PREFIX = {
        {"uint8", "uint8"}, {"int8", "int8"},
        {"uint16", "uint16"}, {"int16", "int16"},
        {"uint32", "uint32"}, {"int32", "int32"},
        {"uint64", "uint64"}, {"int64", "int64"},
        {"float32", "float"}, {"float64", "double"},
        {"float", "float"}, {"double", "double"},
        {"string", "string"},
    };

    const std::map<std::string, std::string> TYPES_MEMBER_PREFIX = {
        {"uint8", "u8"}, {"int8", "i8"},
        {"uint16", "u16"}, {"int16", "i16"},
        {"uint32", "u32"}, {"int32", "i32"},
        {"uint64", "u64"}, {"int64", "i64"},
        {"float32", "f32"}, {"float64", "f64"},
        {"float", "f32"}, {"double", "f64"},
        {"string", "sz"}, {"array", "a"},
    };

    const std::map<std::string, std::string> TYPES_MEMBER_CONVERT_FUNCS = {
        {"uint8", "(uint8_t)strtoul"}, {"int8", "(int8_t)strtol"},
        {"uint16", "(uint16_t)strtoul"}, {"int16", "(int16_t)strtol"},
        {"uint32", "strtoul"}, {"int32", "strtol"},
        {"uint64", "strtoull"}, {"int64", "strtoll"},
        {"float32", "strtof"}, {"float64", "strtold"},
        {"float", "strtof"}, {"double", "strtold"},
    };

    const std::set<std::string> TYPES_MEMBER_CONVERT_NO_BASE = {
        "float32", "float64", "float", "double"
    };

    void CGenerator::Reset(const std::string& srcfile)
    {
        m_sDefaultArraySize = "";
        m_sDefaultStringSize = "";
        m_sFieldEncodeSize = "";
        CodeGenerator::Reset(srcfile);
    }

    void CGenerator::HandleImport(const std::string& imports)
    {
        std::string srcfile = m_sSrcDir + "/" + imports;
        std::shared_ptr<CGenerator> cppGen = std::make_shared<CGenerator>(m_sSrcDir, m_sOutDir);
        std::shared_ptr<CodeGenerator> gen = cppGen;
        std::shared_ptr<CodeHandler> hdr = std::make_shared<CodeHandler>(gen);
        Parser parser;
        parser.SetHandler(hdr);
        cppGen->Reset(srcfile);
        parser.ParseFile(srcfile);
        m_oImports.push_back(cppGen->GetHeadFile());
        // 常量映射
        for (auto& iter : cppGen->GetConstMap())
        {
            m_oConstMap[cppGen->GetPackage() + "." + iter.first] = iter.second;
        }
    }

    void CGenerator::HandleOption(const std::string& name, const std::string& value)
    {
        if (name == "c_max_array_size")
        {
            m_sDefaultArraySize = value;
        }
        else if (name == "c_max_string_size")
        {
            m_sDefaultStringSize = value;
        }
        else if (name == "c_max_message_encode_size")
        {
            m_sFieldEncodeSize = value;
        }
         else if (name == "c_json" || name == "c_json")
        {
            m_sJsonType = value;
        }
    }

    void CGenerator::HandleConst(const std::shared_ptr<FieldInfo>& fieldInfo)
    {
        CodeGenerator::HandleConst(fieldInfo);
        // 常量缓存
        m_oConstMap[fieldInfo->GetName()] = fieldInfo->GetName();
    }

    // 处理pp文件中的enum定义
    void CGenerator::HandleEnum(const std::shared_ptr<StructInfo>& structInfo)
    {
        CodeGenerator::HandleEnum(structInfo);
        // 常量缓存
        for (auto& v : structInfo->GetFields())
        {
            m_oConstMap[v->GetName()] = v->GetName();
        }
    }

    // 处理pp文件中的message定义
    void CGenerator::HandleStruct(const std::shared_ptr<StructInfo>& structInfo)
    {
        CodeGenerator::HandleStruct(structInfo);
        m_oConstMap[structInfo->GetName()] = structInfo->GetName();
    }

    // 返回生成的文件名
    std::string CGenerator::GetHeadFile()
    {
        std::string filename = GetFileName(m_sSrcFile);
        std::string relpath = GetRelativePath(m_sSrcDir, m_sSrcFile) + ToLower(Replace(GetNameSpace(), ".", "/"));
        return relpath + "/" + filename + ".h";
    }

    void CGenerator::Generate()
    {
        std::string filename = GetFileName(m_sSrcFile);
        std::string relpath = GetRelativePath(m_sSrcDir, m_sSrcFile) + ToLower(Replace(GetNameSpace(), ".", "/"));
        std::string outpath = m_sOutDir + "/" + relpath + "/";

        try
        {
            CreateDirectories(outpath);
            // 生成头文件
            std::cout << "    --> " << outpath << filename << ".h" << std::endl;
            GenerateHeadFile(outpath, filename);
            std::cout << "    --> " << outpath << filename << ".c" << std::endl;
            GenerateCFile(outpath, filename);
        }
        catch (const std::exception& e)
        {
            std::cerr << M_ERR_COLOR_START "error: generate source code for file '" << m_sSrcFile << "' fail:"
                << e.what() << M_ERR_COLOR_END << std::endl;
        }
    }

    // 生成头文件内容
    void CGenerator::GenerateHeadFile(const std::string& outdir, const std::string& filename)
    {
        std::string headfile = outdir + filename + ".h";

        // 打开文件
        std::ofstream ofs(headfile, std::ios::out | std::ios::trunc);

        if (!ofs.is_open())
        {
            std::cerr << M_ERR_COLOR_START << "error: fail to open file '" << headfile
                << "' to write" << M_ERR_COLOR_END << std::endl;
            return;
        }

        ofs << "/**" << std::endl
            << " * Code generated by pp_gen_c. DO NOT EDIT." << std::endl
            << " * versions:" << std::endl
            << " *     pp_gen_c " PP_GEN_C_VERSION << std::endl
            << " *     pp_gen   " PP_GEN_VERSION << std::endl
            << " * source: " << TrimPath(m_sSrcFile) << std::endl
            << " */" << std::endl << std::endl;

        GenerateHeadMacro(ofs, filename);
        GenerateHeadImport(ofs);
        GenerateHeadClassDeclare(ofs);
        GenerateHeadConst(ofs);
        GenerateHeadEnum(ofs);
        GenerateHeadClass(ofs);
        GenerateHeadFunction(ofs);

        // 头文件结尾
        ofs << "#endif" << std::endl;

        ofs.close();
    }

    // 头文件宏定义
    void CGenerator::GenerateHeadMacro(std::ofstream& ofs, const std::string& filename)
    {
        std::string fmacro = GetFileMacro(filename);
        ofs << "#ifndef " << fmacro << "_H" << std::endl
            << "#define " << fmacro << "_H" << std::endl << std::endl;
    }

    // 头文件include
    void CGenerator::GenerateHeadImport(std::ofstream& ofs)
    {
        if (m_sJsonType == JSON_TYPE_NATIVE)
        {
            ofs << "#include \"pp/jsonloader.h\"" << std::endl;
        }
        if (m_oImports.empty())
        {
            ofs << "#include \"pp/message.h\"" << std::endl << std::endl;
        }
        else
        {
            for (auto& v: m_oImports)
            {
                ofs << "#include \"" << v << "\"" << std::endl;
            }
            ofs << std::endl;
        }
    }

    // 头文件类声明
    void CGenerator::GenerateHeadClassDeclare(std::ofstream& ofs)
    {
        std::string nsi = GetNameSpaceIndentation();
        for (auto& v: m_oStructs)
        {
            ofs << nsi << "typedef struct " << v->GetName() << " " << v->GetName() << ";" << std::endl;
        }

        if (!m_oStructs.empty()) ofs << std::endl;
    }

    // 头文件宏定义
    void CGenerator::GenerateHeadConst(std::ofstream& ofs)
    {
        std::string nsi = GetNameSpaceIndentation();
        std::vector<std::string> clist;
        uint32_t maxName = 0;
        uint32_t maxlen = 0;

        // 以下逻辑的目的，先算出const的最大长度，目的是为了对齐
        for (auto& v: m_oConsts)
        {
            if (v->GetName().size() > maxName) maxName = v->GetName().size();
        }

        for (auto& v: m_oConsts)
        {
            std::string qoutes = v->GetType() == "string" ? "\"" : "";
            std::stringstream ss;
            ss << nsi << "#define " << v->GetName() << "    ";
            // 补齐空格以对齐
            for (int j = 0; j < (int)(maxName - v->GetName().size()); j++) ss << " ";
            ss << qoutes << v->GetValue() << qoutes;
            std::string sval = ss.str();
            if (sval.length() > maxlen) maxlen = sval.length();
            clist.push_back(sval);
        }

        // 对齐注释，输出到文件
        for (size_t i = 0; i < clist.size(); i++)
        {
            auto v = m_oConsts[i];
            std::string sval = clist[i];

            ofs << sval;
            if (!v->GetDesc().empty())
            {
                for (int j = 0; j < (int)(maxlen - sval.size()); j++) ofs << " ";
                ofs << "    /* " << v->GetDesc() << " */";
            }
            ofs << std::endl;
        }

        if (!m_oConsts.empty()) ofs << std::endl;
    }

    // 头文件枚举定义
    void CGenerator::GenerateHeadEnum(std::ofstream& ofs)
    {
        std::string nsi = GetNameSpaceIndentation();

        for (auto& v : m_oEnums)
        {
            if (!v->GetDesc().empty()) ofs << nsi << "/* " << v->GetDesc() << " */" << std::endl;
            ofs << nsi << "enum " << v->GetName() << std::endl
                << nsi << "{" << std::endl;
            GenerateHeadEnumValues(ofs, v->GetFields());
            ofs << nsi << "};" << std::endl << std::endl;
        }
    }

    // 头文件枚举值
    void CGenerator::GenerateHeadEnumValues(std::ofstream& ofs, const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        std::string nsi = GetNameSpaceIndentation();
        std::vector<std::string> clist;
        uint32_t maxlen = 0;

        // 以下逻辑的目的，先算出最大长度，目的是为了对齐注释
        for (auto& v: vals)
        {
            std::stringstream ss;
            ss << nsi << CODE_INDENTATION << v->GetName() << " = " << v->GetValue() << ",";
            std::string sval = ss.str();
            if (sval.length() > maxlen) maxlen = sval.length();
            clist.push_back(sval);
        }

        // 对齐注释，输出到文件
        for (size_t i = 0; i < clist.size(); i++)
        {
            auto v = vals[i];
            std::string sval = clist[i];

            ofs << sval;
            if (!v->GetDesc().empty())
            {
                for (size_t j = 0; j < maxlen - sval.size(); j++) ofs << " ";
                ofs << "    /* " << v->GetDesc() << " */";
            }
            ofs << std::endl;
        }
    }

    // 头文件消息类定义
    void CGenerator::GenerateHeadClass(std::ofstream& ofs)
    {
        std::string nsi = GetNameSpaceIndentation();

        for (auto& v : m_oStructs)
        {
            std::string className = v->GetName();

            if (!v->GetDesc().empty()) ofs << nsi << "/* " << v->GetDesc() << " */" << std::endl;
            ofs << nsi << "struct " << className<< std::endl
                << nsi << "{" << std::endl;
            // 类成员定义
            GenerateHeadClassAttributes(ofs, v->GetType() == STRUCT_TYPE_ONEOF, v->GetFields());
            ofs << nsi << "};" << std::endl << std::endl;
        }
    }

    // 头文件消息类成员定义
    void CGenerator::GenerateHeadClassAttributes(std::ofstream& ofs, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        if (vals.empty()) return;

        std::string nsi = GetNameSpaceIndentation();

        std::vector<std::string> clist;
        uint32_t maxlen = 0;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "uint32_t u32Selector;" << std::endl
                << nsi << CODE_INDENTATION << "union" << std::endl
                << nsi << CODE_INDENTATION << "{" << std::endl;
            nsi += CODE_INDENTATION;
        }

        // 以下逻辑的目的，先算出最大长度，目的是为了对齐注释
        for (auto& v: vals)
        {
            std::string memberName = ToPascalCase(v->GetName());
            // 数组字段长度声明
            if (v->GetType() == "array")
            {
                std::stringstream ss;
                ss << nsi << CODE_INDENTATION << "uint32_t u32" << memberName << "Number;";
                std::string sval = ss.str();
                if (sval.length() > maxlen) maxlen = sval.length();
                clist.push_back(sval);
            }
            // 字段申明
            std::stringstream ss;
            ss << nsi << CODE_INDENTATION << GetClassAttribute(v->GetType(), v->GetSubType(), memberName, v->GetSize());
            std::string sval = ss.str();
            if (sval.length() > maxlen) maxlen = sval.length();
            clist.push_back(sval);
        }

        // 对齐注释，输出到文件
        int ai = 0;
        for (size_t i = 0; i < clist.size(); i++)
        {
            auto v = vals[i - ai];

            if (v->GetType() == "array")
            {
                std::string sval = clist[i];
                ofs << sval;
                if (!v->GetDesc().empty())
                {
                    for (size_t j = 0; j < maxlen - sval.size(); j++) ofs << " ";
                    ofs << "    /* number of " << v->GetDesc() << " */";
                }
                ofs << std::endl;
                ai++;
                i++;
            }

            std::string sval = clist[i];

            ofs << sval;
            if (!v->GetDesc().empty())
            {
                for (size_t j = 0; j < maxlen - sval.size(); j++) ofs << " ";
                ofs << "    /* " << v->GetDesc() << " */";
            }
            ofs << std::endl;
        }

        if (bUnion)
        {
            ofs << nsi << "};" << std::endl;
        }
    }

    // 头文件消息函数
    void CGenerator::GenerateHeadFunction(std::ofstream& ofs)
    {
        ofs << "#ifdef __cplusplus" << std::endl
            << "extern \"C\"" << std::endl
            << "{" << std::endl
            << "#endif" << std::endl << std::endl;

        std::string nsi = GetNameSpaceIndentation();

        for (auto& v : m_oStructs)
        {
            std::string className = v->GetName();
            std::string funcName = ToCCase(v->GetName());
            std::string memberName = ToPascalCase(v->GetName());

            ofs << nsi << "/* functions for message " << className << " */" << std::endl;

            // 初始化函数
            ofs << nsi << "void " << funcName << "_init(" << className << "* pst" << memberName << ");" << std::endl;

            // encode函数
            ofs << nsi << "int " << funcName << "_encode(" << className << "* pst" << memberName
                << ", LPBYTEARRAY pstByteArray, uint64_t u64Tag);" << std::endl;

            // decode函数
            ofs << nsi << "int " << funcName << "_decode(" << className << "* pst" << memberName
                << ", const char* szBuf, uint32_t u32Len);" << std::endl;

            // to string函数
            ofs << nsi << "void " << funcName << "_to_string(" << className << "* pst" << memberName
                << ", LPSTRING pString);" << std::endl;

            // to json函数
            ofs << nsi << "void " << funcName << "_to_json(" << className << "* pst" << memberName
                << ", LPSTRING pString);" << std::endl;

            if (m_sJsonType == JSON_TYPE_NATIVE)
            {
                // from json函数
                ofs << nsi << "int " << funcName << "_from_json(" << className << "* pst" << memberName
                    << ", const char* szJson);" << std::endl;
                // from json file函数
                ofs << nsi << "int " << funcName << "_from_json_file(" << className << "* pst" << memberName
                    << ", const char* szJsonFile);" << std::endl;
                // from json node
                ofs << nsi << "int " << funcName << "_from_json_node(" << className << "* pst" << memberName
                    << ", JsonNode* pstJsonNode);" << std::endl;
            }

            ofs << std::endl;
        }

        ofs << "#ifdef __cplusplus" << std::endl
            << "}" << std::endl
            << "#endif" << std::endl << std::endl;
    }

    // 生成实现文件内容
    void CGenerator::GenerateCFile(const std::string& outdir, const std::string& filename)
    {
        std::string cppfile = outdir + filename + ".c";

        // 打开文件
        std::ofstream ofs(cppfile, std::ios::out | std::ios::trunc);

        if (!ofs.is_open())
        {
            std::cerr << M_ERR_COLOR_START << "error: fail to open file '" << cppfile
                << "' to write" << M_ERR_COLOR_END << std::endl;
            return;
        }

        ofs << "/**" << std::endl
            << " * Code generated by pp_gen_c. DO NOT EDIT." << std::endl
            << " * versions:" << std::endl
            << " *     pp_gen_c " PP_GEN_C_VERSION << std::endl
            << " *     pp_gen   " PP_GEN_VERSION << std::endl
            << " * source: " << TrimPath(m_sSrcFile) << std::endl
            << " */" << std::endl << std::endl
            << "#include \"" << filename << ".h\"" << std::endl << std::endl
            << "#include <string.h>" << std::endl;
        if (m_sJsonType == JSON_TYPE_NATIVE) ofs << "#include <stdlib.h>" << std::endl;
        ofs << std::endl;

        GenerateCppClass(ofs);

        ofs.close();
    }

    // CPP文件类实现函数
    void CGenerator::GenerateCppClass(std::ofstream& ofs)
    {
        std::string nsi = GetNameSpaceIndentation();
        int i = 0;

        for (auto& v : m_oStructs)
        {
            std::string className = v->GetName();
            std::string funcName = ToCCase(v->GetName());
            std::string memberName = ToPascalCase(v->GetName());

            if (i++ > 0) ofs << std::endl;

            bool bUnion = v->GetType() == STRUCT_TYPE_ONEOF;

            // 初始化函数
            ofs << nsi << "/* init function for message: " << className << " */" << std::endl
                << nsi << "void " << funcName << "_init(" << className << "* pst" << memberName << ")" << std::endl
                << nsi << "{" << std::endl;
            GenerateInitFunction(ofs, memberName, bUnion, v->GetFields());
            ofs << nsi << "}" << std::endl << std::endl;

            // 编码函数
            ofs << nsi << "/* encode function for message: " << className << " */" << std::endl
                << nsi << "int " << funcName << "_encode(" << className << "* pst" << memberName
                << ", LPBYTEARRAY pstByteArray, uint64_t u64Tag)" << std::endl
                << nsi << "{" << std::endl;
            GenerateEncodeFunction(ofs, memberName, bUnion, v->GetFields());
            ofs << nsi << CODE_INDENTATION << "return 0;" << std::endl
                << nsi << "}" << std::endl << std::endl;

            // 子字段解码函数
            ofs << nsi << "/* sub field decode function for message: " << className << " */" << std::endl
                << nsi << "int " << funcName << "_sub_field_decode(void* pstMessage, uint64_t u64Tag, const char* szBuf, uint32_t u32HeadLen, uint32_t u32DataLen)" << std::endl
                << nsi << "{" << std::endl;
            GenerateDecodeFunction(ofs, className, bUnion, v->GetFields());
            ofs << nsi << CODE_INDENTATION << "return 0;" << std::endl
                << nsi << "}" << std::endl << std::endl;

            // 解码函数
            ofs << nsi << "/* decode function for message: " << className << " */" << std::endl
                << nsi << "int " << funcName << "_decode(" << className << "* pst" << memberName
                << ", const char* szBuf, uint32_t u32Len)" << std::endl
                << nsi << "{" << std::endl
                << nsi << CODE_INDENTATION << funcName << "_init(pst" << memberName << ");" << std::endl
                << nsi << CODE_INDENTATION << "return pp_message_decode(pst" << memberName << ", szBuf, u32Len, "
                << funcName << "_sub_field_decode);" << std::endl
                << nsi << "}" << std::endl << std::endl;

            // to_string
            ofs << nsi << "/* to string function for message: " << className << " */" << std::endl
                << nsi << "void " << funcName << "_to_string(" << className << "* pst" << memberName
                << ", LPSTRING pString)" << std::endl
                << nsi << "{" << std::endl;
            GenerateToStringFunction(ofs, memberName, bUnion, v->GetFields());
            ofs << nsi << "}" << std::endl << std::endl;

            // to_json
            ofs << nsi << "/* to json function for message: " << className << " */" << std::endl
                << nsi << "void " << funcName << "_to_json(" << className << "* pst" << memberName
                << ", LPSTRING pString)" << std::endl
                << nsi << "{" << std::endl;
            GenerateToJsonFunction(ofs, memberName, bUnion, v->GetFields());
            ofs << nsi << "}" << std::endl;

            if (m_sJsonType == JSON_TYPE_NATIVE)
            {
                ofs << std::endl;

                // from_json_node
                ofs << nsi << "/* from json node function for message: " << className << " */" << std::endl
                    << nsi <<  "int " << funcName << "_sub_field_from_json(void* pstMessage, JsonNode* pstJsonNode)" << std::endl
                    << nsi << "{" << std::endl;
                    GenerateFromJsonFunction(ofs, className, bUnion, v->GetFields());
                ofs << nsi << CODE_INDENTATION << "return iRet;" << std::endl
                    << nsi << "}" << std::endl << std::endl;

                // from_json
                ofs << nsi << "/* from json function for message: " << className << " */" << std::endl
                    << nsi << "int " << funcName << "_from_json(" << className << "* pst" << memberName
                    << ", const char* szJson)" << std::endl
                    << nsi << "{" << std::endl
                    << nsi << CODE_INDENTATION << funcName << "_init(pst" << memberName << ");" << std::endl
                    << nsi << CODE_INDENTATION << "return message_from_json(pst" << memberName << ", szJson, "
                    << funcName << "_sub_field_from_json);" << std::endl
                    << nsi << "}" << std::endl << std::endl;

                // from_json_file
                ofs << nsi << "/* from json file function for message: " << className << " */" << std::endl
                    << nsi <<  "int " << funcName << "_from_json_file(" << className << "* pst" << memberName
                    << ", const char* szJsonFile)" << std::endl
                    << nsi << "{" << std::endl
                    << nsi << CODE_INDENTATION << funcName << "_init(pst" << memberName << ");" << std::endl
                    << nsi << CODE_INDENTATION << "return message_from_json_file(pst" << memberName << ", szJsonFile, "
                    << funcName << "_sub_field_from_json);" << std::endl
                    << nsi << "}" << std::endl << std::endl;

                // from_json_node
                ofs << nsi << "/* from json node function for message: " << className << " */" << std::endl
                    << nsi <<  "int " << funcName << "_from_json_node(" << className << "* pst" << memberName
                    << ", JsonNode* pstJsonNode)" << std::endl
                    << nsi << "{" << std::endl
                    << nsi << CODE_INDENTATION << funcName << "_init(pst" << memberName << ");" << std::endl
                    << nsi << CODE_INDENTATION << "return message_from_json_node(pst" << memberName << ", pstJsonNode, "
                    << funcName << "_sub_field_from_json);" << std::endl
                    << nsi << "}" << std::endl;
            }
        }
    }

    // CPP文件构造函数
    void CGenerator::GenerateInitFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        if (vals.empty()) return;

        std::string nsi = GetNameSpaceIndentation();

        ofs << nsi << CODE_INDENTATION << "if (NULL == pst" << classMemberName << ") return;" << std::endl << std::endl;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "pst" << classMemberName << "->u32Selector = 0xFFFFFFFF;" << std::endl;
            return;
        }

        for (auto& v: vals)
        {
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            if (v->GetType() == "string")
            {
                if (v->GetDefault().empty())
                {
                    ofs << nsi << CODE_INDENTATION << "*pst" << classMemberName << "->" << memberName << " = 0;" << std::endl;
                }
                else
                {
                    ofs << nsi << CODE_INDENTATION << "memcpy(pst" << classMemberName << "->" << memberName
                        << ", " << GetImportValue(v->GetDefault(), true)
                        << ", sizeof(pst" << classMemberName << "->" << memberName << "));" << std::endl
                        << nsi << CODE_INDENTATION << "pst" << classMemberName << "->" << memberName
                        << "[sizeof(pst" << classMemberName << "->" << memberName << ") - 1] = 0;" << std::endl;
                }
            }
            else if (v->GetType() == "array")
            {
                ofs << nsi << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number = 0;" << std::endl;
            }
            else
            {
                auto iter = TYPES_MAP.find(v->GetType());
                if (iter != TYPES_MAP.end())
                {
                    std::string defVal = v->GetDefault().empty() ? "0" : GetImportValue(v->GetDefault(), false);
                    ofs << nsi << CODE_INDENTATION << "pst" << classMemberName << "->" << memberName << " = "
                        << defVal << ";" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << funcName << "_init(&pst" << classMemberName << "->" << memberName << ");" << std::endl;
                }
            }
        }
    }

    // CPP文件编码函数
    void CGenerator::GenerateEncodeFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion,
        const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        if (vals.empty()) return;

        std::string nsi = GetNameSpaceIndentation();
        ofs << nsi << CODE_INDENTATION << "char szBuf[" << GetFieldEncodeSize() << "];" << std::endl
            << nsi << CODE_INDENTATION << "BYTEARRAY baBuf;" << std::endl
            << nsi << CODE_INDENTATION << "int iRet;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "if (NULL == pst" << classMemberName << " || NULL == pstByteArray) return ERROR_INPUT_PARAM_NULL;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "INIT_BYTE_ARRAY(baBuf, szBuf, sizeof(szBuf));" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "/* Encode sub field */" << std::endl;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "switch (pst" << classMemberName << "->u32Selector)" << std::endl
                << nsi << CODE_INDENTATION << "{" << std::endl;
            nsi += CODE_INDENTATION;
        }

        for (auto& v: vals)
        {
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            if (bUnion)
            {
                ofs << nsi << "case " << GetImportValue(v->GetTag()) << ":" << std::endl;
            }

            if (v->GetType() == "array")
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetSubType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_FIELD_ENCODE(baBuf, " << GetImportValue(v->GetTag())
                        << ", pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, "
                        << iter->second << ", iRet);" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetSubType()));
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_STRUCT_ENCODE(baBuf, " << GetImportValue(v->GetTag())
                        << ", pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, "
                        << funcName << ", iRet);" << std::endl;
                }
            }
            else
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "PP_CHECK_FUNC_RET(" << iter->second << "_field_encode(&baBuf, "
                        << GetImportValue(v->GetTag()) << ", pst" << classMemberName << "->"
                        << memberName << "), iRet);" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << "PP_CHECK_FUNC_RET(" << funcName << "_encode(&pst" << classMemberName << "->"
                        << memberName << ", &baBuf, " << GetImportValue(v->GetTag()) << "), iRet);" << std::endl;
                }
            }

            if (bUnion) ofs << nsi << CODE_INDENTATION << "break;" << std::endl;
        }

        if (bUnion)
        {
            ofs << nsi << "default:" << std::endl
                << nsi << CODE_INDENTATION << "break;" << std::endl
                << nsi << "}" << std::endl;
            nsi = GetNameSpaceIndentation();
        }

        ofs << std::endl << nsi << CODE_INDENTATION << "/* Encode the entire field */" << std::endl
            << nsi << CODE_INDENTATION << "PP_CHECK_FUNC_RET(bytearray_append_varint(pstByteArray, u64Tag), iRet);" << std::endl
            << nsi << CODE_INDENTATION << "PP_CHECK_FUNC_RET(bytearray_append_varint(pstByteArray, baBuf.dwLen), iRet);" << std::endl
            << nsi << CODE_INDENTATION << "PP_CHECK_FUNC_RET(bytearray_append_string(pstByteArray, baBuf.pszData, baBuf.dwLen), iRet);" << std::endl;
    }

    // CPP文件解码函数
    void CGenerator::GenerateDecodeFunction(std::ofstream& ofs, const std::string& className, bool bUnion,
        const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        if (vals.empty()) return;

        std::string nsi = GetNameSpaceIndentation();
        std::string classMemberName = ToPascalCase(className);

        ofs << nsi << CODE_INDENTATION << className << "* pst" << classMemberName
            << " = (" << className << "*)pstMessage;" << std::endl
            << nsi << CODE_INDENTATION << "int iRet = 0;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "if (NULL == pstMessage || NULL == szBuf) return ERROR_INPUT_PARAM_NULL;" << std::endl << std::endl;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "pst" << classMemberName << "->u32Selector = (uint32_t)u64Tag;" << std::endl << std::endl;
        }

        ofs << nsi << CODE_INDENTATION << "switch (u64Tag)" << std::endl
            << nsi << CODE_INDENTATION << "{" << std::endl;

        for (auto& v: vals)
        {
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            if (v->GetType() == "array")
            {
                std::string arraySize = v->GetSize().empty() ? GetDefaultArraySize() : v->GetSize();
                if (v->GetSubType() == "string")
                {
                    ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "PP_CHECK_FUNC_RET(string_field_decode(szBuf + u32HeadLen, u32DataLen, pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName << "Number]," << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "sizeof(pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName << "Number])), iRet);" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
                    continue;
                }
                auto iter = TYPES_FUNC_PREFIX.find(v->GetSubType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "PP_CHECK_FUNC_RET(" << iter->second << "_field_decode(szBuf + u32HeadLen, u32DataLen, &pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName << "Number]), iRet);" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetSubType()));
                    ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "PP_CHECK_FUNC_RET(" << funcName << "_decode(&pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName << "Number], szBuf, u32HeadLen + u32DataLen), iRet);" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
                }
            }
            else if (v->GetType() == "string")
            {
                ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                    << nsi << CODE_INDENTATION << CODE_INDENTATION
                    << "PP_CHECK_FUNC_RET(string_field_decode(szBuf + u32HeadLen, u32DataLen, pst"
                    << classMemberName << "->" << memberName << ", sizeof(pst"
                    << classMemberName << "->" << memberName << ")), iRet);" << std::endl
                    << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
            }
            else
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION
                        << "PP_CHECK_FUNC_RET(" << iter->second << "_field_decode(szBuf + u32HeadLen, u32DataLen, &pst"
                        << classMemberName << "->" << memberName << "), iRet);" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << "case " << GetImportValue(v->GetTag()) << ":" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION
                        << "PP_CHECK_FUNC_RET(" << funcName << "_decode(&pst"
                        << classMemberName << "->" << memberName << ", szBuf, u32HeadLen + u32DataLen), iRet);" << std::endl
                        << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl;
                }
            }
        }

        ofs << nsi << CODE_INDENTATION << "default:" << std::endl
            << nsi << CODE_INDENTATION << CODE_INDENTATION << "break;" << std::endl
            << nsi << CODE_INDENTATION << "}" << std::endl;
    }

    // CPP文件ToJson函数
    void CGenerator::GenerateToJsonFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        std::string nsi = GetNameSpaceIndentation();
        ofs << nsi << CODE_INDENTATION << "if (NULL == pst" << classMemberName << " || NULL == pString) return;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "pp_string_append_char(pString, '{');" << std::endl << std::endl;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "switch (pst" << classMemberName << "->u32Selector)" << std::endl
                << nsi << CODE_INDENTATION << "{" << std::endl;
            nsi += CODE_INDENTATION;
        }

        for (auto& v: vals)
        {
            std::string jsonName = v->GetJsonName().empty() ? v->GetName() : v->GetJsonName();
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            if (bUnion)
            {
                ofs << nsi << "case " << GetImportValue(v->GetTag()) << ":" << std::endl;
            }

            if (v->GetType() == "array")
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetSubType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_FIELD_TOJSON(pString, pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, \""
                        << jsonName << "\", " << iter->second << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetSubType()));
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_STRUCT_TOJSON(pString, pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, \""
                        << jsonName << "\", " << funcName << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
            }
            else
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << iter->second << "_field_to_json(pString, \""
                        << jsonName << "\", pst" << classMemberName << "->" << memberName << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << "pp_string_append_string(pString, \"\\\"" << jsonName << "\\\": \");" << std::endl
                        << nsi << CODE_INDENTATION << funcName << "_to_json(&pst" << classMemberName << "->" << memberName << ", pString);" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
            }

            if (bUnion) ofs << nsi << CODE_INDENTATION << "break;" << std::endl;
        }

        if (bUnion)
        {
            ofs << nsi << "default:" << std::endl
                << nsi << CODE_INDENTATION << "break;" << std::endl
                << nsi << "}" << std::endl;
            nsi = GetNameSpaceIndentation();
        }

        ofs << std::endl
            << nsi << CODE_INDENTATION << "pp_string_trim_tail(pString, ',');" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "pp_string_append_char(pString, '}');" << std::endl;
    }

    // CPP文件ToString函数
    void CGenerator::GenerateToStringFunction(std::ofstream& ofs, const std::string& classMemberName, bool bUnion, const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        std::string nsi = GetNameSpaceIndentation();
        ofs << nsi << CODE_INDENTATION << "if (NULL == pst" << classMemberName << " || NULL == pString) return;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "pp_string_append_char(pString, '{');" << std::endl << std::endl;

        if (bUnion)
        {
            ofs << nsi << CODE_INDENTATION << "switch (pst" << classMemberName << "->u32Selector)" << std::endl
                << nsi << CODE_INDENTATION << "{" << std::endl;
            nsi += CODE_INDENTATION;
        }

        for (auto& v: vals)
        {
            std::string jsonName = v->GetJsonName().empty() ? v->GetName() : v->GetJsonName();
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            if (bUnion)
            {
                ofs << nsi << "case " << GetImportValue(v->GetTag()) << ":" << std::endl;
            }

            if (v->GetType() == "array")
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetSubType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_FIELD_TOSTRING(pString, pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, \""
                        << jsonName << "\", " << iter->second << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetSubType()));
                    ofs << nsi << CODE_INDENTATION << "PP_ARRAY_STRUCT_TOSTRING(pString, pst" << classMemberName << "->" << memberName
                        << ", pst" << classMemberName << "->u32" << attrName << "Number, \""
                        << jsonName << "\", " << funcName << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
            }
            else
            {
                auto iter = TYPES_FUNC_PREFIX.find(v->GetType());
                if (iter != TYPES_FUNC_PREFIX.end())
                {
                    ofs << nsi << CODE_INDENTATION << iter->second << "_field_to_string(pString, \""
                        << jsonName << "\", pst" << classMemberName << "->" << memberName << ");" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << "pp_string_append_string(pString, \"" << jsonName << ":\");" << std::endl
                        << nsi << CODE_INDENTATION << funcName << "_to_string(&pst" << classMemberName << "->" << memberName << ", pString);" << std::endl
                        << nsi << CODE_INDENTATION << "pp_string_append_char(pString, ',');" << std::endl;
                }
            }

            if (bUnion) ofs << nsi << CODE_INDENTATION << "break;" << std::endl;
        }

        if (bUnion)
        {
            ofs << nsi << "default:" << std::endl
                << nsi << CODE_INDENTATION << "break;" << std::endl
                << nsi << "}" << std::endl;
            nsi = GetNameSpaceIndentation();
        }

        ofs << std::endl
            << nsi << CODE_INDENTATION << "pp_string_trim_tail(pString, ',');" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "pp_string_append_char(pString, '}');" << std::endl;
    }

    // CPP文件FromJson函数
    void CGenerator::GenerateFromJsonFunction(std::ofstream& ofs, const std::string& className, bool bUnion,
        const std::vector<std::shared_ptr<FieldInfo> >& vals)
    {
        if (vals.empty()) return;

        std::string nsi = GetNameSpaceIndentation();
        std::string classMemberName = ToPascalCase(className);

        ofs << nsi << CODE_INDENTATION << className << "* pst" << classMemberName
            << " = (" << className << "*)pstMessage;" << std::endl
            << nsi << CODE_INDENTATION << "int iRet = 0;" << std::endl << std::endl
            << nsi << CODE_INDENTATION << "if (NULL == pstMessage || NULL == pstJsonNode) return ERROR_INPUT_PARAM_NULL;" << std::endl << std::endl;

        std::string sElse = "";

        for (auto& v: vals)
        {
            std::string jsonName = v->GetJsonName().empty() ? v->GetName() : v->GetJsonName();
            std::string attrName = ToPascalCase(v->GetName());
            std::string memberName = GetClassAttributeName(v->GetType(), v->GetSubType(), attrName);

            ofs << nsi << CODE_INDENTATION << sElse << "if (strcmp(pstJsonNode->szName, \"" << jsonName << "\") == 0)" << std::endl
                << nsi << CODE_INDENTATION << "{" << std::endl;

            sElse = "else ";

            if (bUnion)
            {
                ofs << nsi << DOUBLE_CODE_INDENTATION << "pst" << classMemberName << "->u32Selector = " << GetImportValue(v->GetTag()) << ";" << std::endl << std::endl;
            }

            if (v->GetType() == "array")
            {
                std::string arraySize = v->GetSize().empty() ? GetDefaultArraySize() : v->GetSize();
                ofs << nsi << DOUBLE_CODE_INDENTATION << "for (int i = 0; i < pstJsonNode->u32ChildNumber; i++)" << std::endl
                    << nsi << DOUBLE_CODE_INDENTATION << "{" << std::endl;

                if (v->GetSubType() == "string")
                {
                    ofs << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "PP_MSTRNCPY(pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName << "Number], pstJsonNode->astChildren[i]->szValue);" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << "}" << std::endl
                        << nsi << CODE_INDENTATION << "}" << std::endl;
                    continue;
                }
                auto iter = TYPES_MEMBER_CONVERT_FUNCS.find(v->GetSubType());
                if (iter != TYPES_MEMBER_CONVERT_FUNCS.end())
                {
                    std::string vbase = TYPES_MEMBER_CONVERT_NO_BASE.find(v->GetSubType()) == TYPES_MEMBER_CONVERT_NO_BASE.end() ? ", 10" : "";
                    ofs << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->" << memberName
                        << "[pst" << classMemberName << "->u32" << attrName << "Number] = " << iter->second << "(pstJsonNode->astChildren[i]->szValue, NULL" << vbase << ");" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetSubType()));
                    ofs << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "if (pst" << classMemberName << "->u32" << attrName
                        << "Number >= " << arraySize << ") return ERROR_DECODE_ARRAY_LONG;" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "PP_CHECK_FUNC_RET(" << funcName << "_from_json_node(&pst"
                        << classMemberName << "->" << memberName << "[pst" << classMemberName << "->u32" << attrName
                        << "Number], pstJsonNode->astChildren[i]), iRet);" << std::endl
                        << nsi << DOUBLE_CODE_INDENTATION << CODE_INDENTATION << "pst" << classMemberName << "->u32" << attrName << "Number++;" << std::endl;
                }
                ofs << nsi << DOUBLE_CODE_INDENTATION << "}" << std::endl
                    << nsi << CODE_INDENTATION << "}" << std::endl;
            }
            else if (v->GetType() == "string")
            {
                ofs << nsi << DOUBLE_CODE_INDENTATION << "PP_MSTRNCPY(pst" << classMemberName << "->"
                    << memberName << ", pstJsonNode->szValue);" << std::endl
                    << nsi << CODE_INDENTATION << "}" << std::endl;
            }
            else
            {
                auto iter = TYPES_MEMBER_CONVERT_FUNCS.find(v->GetType());
                if (iter != TYPES_MEMBER_CONVERT_FUNCS.end())
                {
                    std::string vbase = TYPES_MEMBER_CONVERT_NO_BASE.find(v->GetType()) == TYPES_MEMBER_CONVERT_NO_BASE.end() ? ", 10" : "";
                    ofs << nsi << DOUBLE_CODE_INDENTATION << "pst" << classMemberName << "->" << memberName << " = "
                        << iter->second << "(pstJsonNode->szValue, NULL" << vbase << ");" << std::endl
                        << nsi << CODE_INDENTATION << "}" << std::endl;
                }
                else
                {
                    std::string funcName = ToCCase(GetImportValue(v->GetType()));
                    ofs << nsi << CODE_INDENTATION << CODE_INDENTATION
                        << "return " << funcName << "_from_json_node(&pst"
                        << classMemberName << "->" << memberName << ", pstJsonNode);" << std::endl;

                    ofs << nsi << CODE_INDENTATION << "}" << std::endl;
                }
            }
        }
    }

    std::string CGenerator::GetFileMacro(const std::string& filename)
    {
        std::stringstream result;
        for (size_t i = 0; i < filename.length(); i++)
        {
            char ch = filename.at(i);
            if (ch >= 'a' && ch <= 'z')
            {
                char u = std::toupper(ch);
                result << u;
            }
            else if ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))
            {
                result << ch;
            }
            else
            {
                result << "_";
            }
        }
        return result.str();
    }

    // 返回数据类型
    std::string CGenerator::GetClassType(const std::string& ftype)
    {
        auto iter = TYPES_MAP.find(ftype);
        if (iter != TYPES_MAP.end()) return iter->second;
        return GetImportValue(ftype);
    }

    // 返回类成员定义
    std::string CGenerator::GetClassAttribute(const std::string& ftype, const std::string& subtype,
        const std::string& name, const std::string& arraySize)
    {
        std::string memberName = GetClassAttributeName(ftype, subtype, name);

        if (ftype == "string")
        {
            std::string size = arraySize.empty() ? GetDefaultStringSize() : arraySize;
            return "char " + memberName + "[" + size + "];";
        }
        else if (ftype == "array")
        {
            std::string size = arraySize.empty() ? GetDefaultArraySize() : arraySize;
            if (subtype == "string")
            {
                return "char " + memberName + "[" + size + "][" + GetDefaultStringSize() + "];";
            }
            auto iter = TYPES_MAP.find(subtype);
            if (iter != TYPES_MAP.end()) return iter->second + " " + memberName + "[" + size + "];";
            return GetImportValue(subtype) + " " + memberName + "[" + size + "];";
        }
        auto iter = TYPES_MAP.find(ftype);
        if (iter != TYPES_MAP.end())
        {
            return iter->second + " " + memberName + ";";
        }
        return GetImportValue(ftype) + " " + memberName + ";";
    }

    // 返回类成员名
    std::string CGenerator::GetClassAttributeName(const std::string& ftype, const std::string& subtype, const std::string& name)
    {
        auto iter = TYPES_MEMBER_PREFIX.find(ftype);
        if (iter != TYPES_MEMBER_PREFIX.end()) return iter->second + name;
        return "st" + name;
    }

    // 从常量数据中返回
    std::string CGenerator::GetImportValue(const std::string& constVal, bool bstring)
    {
        auto iter = m_oConstMap.find(constVal);
        if (iter != m_oConstMap.end()) return iter->second;
        return bstring ? "\"" + constVal + "\"" : constVal;
    }
};
